function isArray(obj) {
	return obj && obj.constructor === Array
}

function isObject(obj) {
	return obj && obj.constructor === Object
}

let socket = new WebSocket(SOCKET_URL)

let map = {}

socket.onopen = function(evt) {
	console.log("socketRequest已连接")
};
socket.onerror = function(evt) {
	console.error("socket未连接，请检查是否启用@SocketRequest，并正确注册了SocketRequestServer组件")
};
socket.onclose = function(evt) {
	console.log("socket连接关闭")
};

socket.onmessage = function(e) {
	let res = JSON.parse(e.data)
	try {
		res.data = JSON.parse(res.data)
	} catch (e) {}
	let callbackObj = map[res.requestId]
	if (callbackObj) {
		clearTimeout(callbackObj.timer)
		let startTime = callbackObj.startTime
		let endTime = new Date().getTime()
		let duration = endTime - startTime
		res.startTime = startTime
		res.duration = duration
		res.endTime = endTime
		callbackObj.callback(res)
		delete map[res.requestId]
	}
};

socket.onclose = function(evt) {
	console.log("socketRequest连接关闭")
};
socket.onerror = function(e) {
	console.log("socketRequest连接错误")
	console.error(e)
};

const DEFAULT_CONFIG = {
	/**
	 * 默认请求方法
	 */
	method: 'GET',
	/**
	 * 请求头
	 */
	headers: {
		'Content-Type': 'application/x-www-form-urlencoded'
	},
	/**
	 * 参数转成QueryString格式
	 */
	paramsSerializer: (data) => {
		if (isObject(data)) {
			let arr = []
			for (let key in data) {
				try {
					if (isObject(data[key]) || isArray(data[key])) {
						arr.push(`${key}=${encodeURI(JSON.stringify(data[key]))}`)
					} else {
						arr.push(`${key}=${encodeURI(data[key])}`)
					}
				} catch (e) {}

			}
			return arr.join("&")
		} else {
			return JSON.stringify(data)
		}
	},
	/**
	 * 超时时间。为0则无限等待
	 */
	timeout: 5000,
	/**
	 * 响应的数据。
	 * 可以是：arraybuffer, json, text, blob
	 */
	responseType: 'json',
	/**
	 * 是否发送Cookie
	 */
	withCredentials: true,
	/**
	 * 上传事件
	 */
	onUploadProgress: undefined,
	/**
	 * 下载事件
	 */
	onDownloadProgress: undefined,
	/**
	 * 代理
	 */
	proxy: undefined
}

function regist(uri, data, option, resolveCallback, rejectCallback) {
	let header = createRequestHeader(option)
	let url = createUrl(uri, data, option)
	let requestId = uuid()
	let postData = createPostData(data, option)
	let method = getMethod(option)

	let request = {
		header,
		url,
		requestId,
		data: postData,
		method
	}
	try {
		console.log("发送socketRequest", request)
		socket.send(JSON.stringify(request))
	} catch (e) {
		rejectCallback(e)
		return
	}

	let timeout = getTimeout(option)
	map[requestId] = {
		callback: resolveCallback,
		timer: setTimeout(() => {
			rejectCallback(new Error("超时"))
			map[requestId] = null
		}, timeout),
		startTime: new Date().getTime()
	}
}
let uid = 0

function getMethod(option) {
	return option?.method || DEFAULT_CONFIG.method || "GET"
}

function uuid() {
	return ++uid + ""
}

function getTimeout(option) {
	return option?.timeout || DEFAULT_CONFIG.timeout || 5000
}

function createPostData(data, option) {
	let method = option?.method || DEFAULT_CONFIG.method || "GET"
	if (method.toUpperCase() !== "GET") {
		return JSON.stringify(data)
	} else {
		return null
	}
}

function createRequestHeader(option) {
	return Object.assign({}, DEFAULT_CONFIG.headers, option?.headers)
}

function createUrl(uri, data, option) {
	if (!data) {
		return uri
	}
	let method = option?.method || DEFAULT_CONFIG.method || "GET"
	if (method.toUpperCase() === "GET") {
		return uri + "?" + (option?.paramsSerializer || DEFAULT_CONFIG.paramsSerializer)(data)
	} else {
		return uri
	}
}

function $sget(uri, data, option) {
	return new Promise((resolve, reject) => {
		regist(uri, data, Object.assign({}, option, {
			method: 'GET'
		}), resolve, reject)
	})
}

function $spost(uri, data, option) {
	return new Promise((resolve, reject) => {
		regist(uri, data, Object.assign({}, option, {
			method: 'POST'
		}), resolve, reject)
	})
}
